package client.network;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import client.controller.MainController;


public class Client {

	private ClientCommand m_commands_thread;
	private String m_id;
	private Socket m_sending_socket;	
	private String m_racine_path;
	private MainController m_controller;
	
	private ClientCommand _clientCommand;
	private ClientSending _clientSending;
	
	public Client(MainController mc)
	{
		_clientCommand = null;
		_clientSending = null;
		m_sending_socket = null;
		m_controller = mc;
		m_racine_path = System.getProperty("user.home");
	}
	
	/**
	 * Essaie d'établir une connexion par socket avec le serveur à l'adresse et au port indiqués
	 * @param address
	 * L'adresse du serveur.
	 * @param port
	 * Le port de communication sur lequel le serveur est à l'écoute.
	 * @return
	 * True si la connexion est établie.
	 * @throws UnknownHostException
	 * @throws IOException
	 */
	public boolean tryConnect(String address, int port) throws UnknownHostException, IOException
	{
		// Le flag de réussite de l'opération de connexion
		boolean success = false;
		
		// La socket qui sert à établir la connexion puis communiquer les commandes
		Socket socketCommand = null;
		
		// On essaie d'établir une connexion avec l'adresse et le port donné
		try
		{
			socketCommand = new Socket(address, port);
			
			// La connexion est établie
			success = true;
		}
		finally
		{
			// Il y a eu une erreur, on ferme et on détruit proprement le socket
			if (!success && socketCommand != null)
			{
				try { socketCommand.close(); }
				catch (IOException e) {}
				socketCommand = null;
			}
		}
		// La connexion est établie, on crée le client qui s'occupe des commandes
		if (success)
		{
			_clientCommand = new ClientCommand(this,socketCommand);
		}
		return success;
	}
	
	/**
	 * Essaie de s'identifier auprès du serveur en utilisant le couple id/password spécifié.
	 * @param id
	 * L'identifiant de l'utilisateur.
	 * @param password
	 * Le mot de passe de l'utilisateur.
	 * @return
	 * True si l'authentification est valide, false sinon.
	 * @throws IOException
	 * @throws AlreadyAuthentifiedException
	 * @throws MaxLoginTryException
	 */
	public boolean tryAuthentify(String id, String password) throws IOException, AlreadyAuthentifiedException, MaxLoginTryException
	{
		boolean success = false;
		
		if (_clientCommand != null)
		{
			_clientCommand.initializeInputOutput();
			success = _clientCommand.authentify(id, password);
			
			// L'authentification a réussie, on récupère l'id
			if (success)
			{
				m_id = id;
			}
		}
		
		return success;
	}
	
	/**
	 * Lance l'exécution des taches asynchrones (gestion des commandes et des données)
	 */
	public void startAsyncTasks()
	{
		if (_clientCommand != null)
		{
			_clientCommand.start();
		}
	}
	
	/**
	 * Ferme proprement les composants ouverts (socket, flux d'entrée/sortie)
	 */
	public void close()
	{
		if (_clientCommand != null)
		{
			_clientCommand.close();
			_clientCommand = null;
		}
		if (_clientSending != null)
		{
			_clientSending.close();
			_clientSending = null;
		}
	}
	
	public ClientCommand getClientCommand()
	{
		return _clientCommand;
	}
	
	public ClientSending getClientSending()
	{
		return _clientSending;
	}
	
	/*
	public Client(String id) {
		m_id = id;
		m_sending_socket = null;
		m_racine_path = System.getProperty("user.home");
		m_commands_thread = new ClientCommand(this);
	}
	*/
	
	public ClientCommand get_commands_thread() {
		return m_commands_thread;
	}
	
	public void set_id(String id){
		m_id = id;
	}
	
	public String get_id(){
		return m_id;
	}

	public Socket get_sending_socket() {
		return m_sending_socket;
	}

	public void set_sending_socket(Socket sending_socket) {
		this.m_sending_socket = sending_socket;
	}
	
	public void set_racine_path(String path_name){
		m_racine_path = path_name;
	}
	
	public String get_racine_path(){
		return m_racine_path;
	}
	
	public MainController get_controller(){
		return m_controller;
	}
	
	public void set_controller(MainController controller){
		m_controller = controller;
	}
}
